home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OCFSRC.PAK / OLEUTIL.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  9KB  |  438 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectComponents
  3. // Copyright (c) 1994, 1997 by Borland International, All Rights Reserved
  4. //
  5. // $Revision:   2.14  $
  6. //
  7. // OLE Utility class implementations
  8. //----------------------------------------------------------------------------
  9. #include <ocf/pch.h>
  10. #if !defined(OCF_DEFS_H)
  11. # include <ocf/defs.h>
  12. #endif
  13. #if !defined(OCF_OLEUTIL_H)
  14. # include <ocf/oleutil.h>
  15. #endif
  16. #if !defined(WINSYS_STRING_H)
  17. # include <winsys/string.h>
  18. #endif
  19. #if !defined(SERVICES_MEMORY_H)
  20. # include <services/memory.h>
  21. #endif
  22. #if !defined (WINSYS_REGISTRY_H)
  23. # include <winsys/registry.h>
  24. #endif
  25. #if !defined (OCF_OCBOCOLE_H)
  26. # include <ocf/ocbocole.h>
  27. #endif
  28.  
  29. DIAG_DEFINE_GROUP(OcRefCount, true, 1);
  30.  
  31. //
  32. //
  33. //
  34. void*
  35. TOleAllocator::Alloc(unsigned long size)
  36. {
  37.   void* blk = Mem->Alloc(size);
  38.   OLECALL(blk ? 0 : HR_OUTOFMEMORY, "IMalloc::Alloc");
  39.   return blk;
  40. }
  41.  
  42. //
  43. //
  44. //
  45. void
  46. TOleAllocator::Free(void* pv)
  47. {
  48.   Mem->Free(pv);
  49. }
  50.  
  51. //----------------------------------------------------------------------------
  52. // TClassId - GUID/IID/CLSID management implementation
  53. //
  54.  
  55. //
  56. //
  57. //
  58. TClassId::TClassId(const char* idtxt)
  59.          :Text(0)
  60. {
  61.   PRECONDITION(idtxt);
  62.   OLECALL(::CLSIDFromString(OleStr((char far*)idtxt), &Guid), "Invalid GUID string");
  63. }
  64.  
  65. //
  66. //
  67. //
  68. TClassId::TClassId(const GUID far& guid, int offset)
  69.          :Text(0), Guid(guid)
  70. {
  71.   Guid.Data1 += (long)offset;
  72. }
  73.  
  74. //
  75. //
  76. //
  77. TClassId::TClassId(TGenerate)
  78.          :Text(0)
  79. {
  80.   OLECALL(::CoCreateGuid(&Guid), "CoCreateGuid");
  81. }
  82.  
  83. //
  84. //
  85. //
  86. TClassId::~TClassId()
  87. {
  88.   delete[] const_cast<char*>(Text);
  89. }
  90.  
  91. //
  92. //
  93. //
  94. TClassId::operator const char*()
  95. {
  96.   if (!Text) {
  97.     Text = new char[38+1];
  98.     wsprintf(const_cast<char*>(Text),
  99.              "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
  100.              Guid.Data1, Guid.Data2, Guid.Data3,
  101.              Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3],
  102.              Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
  103.   }
  104.   return Text;
  105. }
  106.  
  107. //
  108. //
  109. //
  110. TBaseClassId::TBaseClassId(const GUID far& guid, int maxAlloc)
  111.              :TClassId(guid), MaxAlloc(maxAlloc), Offset(0)
  112. {
  113. }
  114.  
  115. //
  116. //
  117. //
  118. TBaseClassId::TBaseClassId(const char far* idtxt, int maxAlloc)
  119.              :TClassId(idtxt), MaxAlloc(maxAlloc), Offset(0)
  120. {
  121. }
  122.  
  123. //
  124. //
  125. //
  126. TBaseClassId::TBaseClassId(TGenerate e, int maxAlloc)
  127.              :TClassId(e), MaxAlloc(maxAlloc), Offset(0)
  128. {
  129. }
  130.  
  131. //
  132. //
  133. //
  134. TBaseClassId::TBaseClassId(TRegList& regInfo, int maxAlloc)
  135.              :TClassId(), MaxAlloc(maxAlloc), Offset(0)
  136. {
  137.   const char* str = regInfo["clsid"];
  138.   if (!str)
  139.     OLECALL(HR_CLASS_CLASSNOTAVAILABLE, "Missing REGDATA clsid");
  140.   OLECALL(::CLSIDFromString(OleStr((char far*)str), &Guid), "Invalid GUID string");
  141. }
  142.  
  143. //
  144. //
  145. //
  146. TClassId
  147. TBaseClassId::operator [](int offset)
  148. {
  149.   if(offset > Offset)
  150.     OLECALL(HR_CLASS_CLASSNOTAVAILABLE, "Unassigned GUID");
  151.   return TClassId(Guid, offset);
  152. }
  153.  
  154. //
  155. //
  156. //
  157. int
  158. TBaseClassId::AllocId()
  159. {
  160.   ++Offset;
  161.   if(Offset >= MaxAlloc)
  162.     OLECALL(HR_CLASS_CLASSNOTAVAILABLE, "GUID allocation exhausted");
  163.   return Offset;
  164. }
  165.  
  166. //
  167. //
  168. //
  169. int
  170. TBaseClassId::GetOffset(const GUID& guid)
  171. {
  172.   unsigned long offset = guid.Data1 - Guid.Data1;
  173.   if ( offset >= (unsigned long)Offset &&
  174.        ((long*)&guid)[1] == ((long*)&Guid)[1] &&
  175.        ((long*)&guid)[2] == ((long*)&Guid)[2] &&
  176.        ((long*)&guid)[3] == ((long*)&Guid)[3] )
  177.     return int(offset);
  178.   else
  179.     return -1;
  180. }
  181.  
  182. //----------------------------------------------------------------------------
  183. // GUID compare routines use by implementations of IUnknown::QueryInterface
  184. //       the low-order long word is verifed before calling these routines
  185. //       success is indicated by virtue of assigment of the returned interface
  186. //
  187.  
  188. #if defined(BI_NAMESPACE)
  189. namespace OCF {
  190. #endif
  191.  
  192. //
  193. //
  194. //
  195. void
  196. CmpGuid12(IUnknown* obj, REFIID req, REFIID ref, void far*far* pif)
  197. {
  198.   if ( ((long far*)&req)[1] == ((long far*)&ref)[1] &&
  199.        ((long far*)&req)[2] == ((long far*)&ref)[2] &&
  200.        ((long far*)&req)[3] == ((long far*)&ref)[3] ) {
  201.     *pif = obj;
  202.     obj->AddRef();
  203.   }
  204. }
  205.  
  206. //
  207. //
  208. //
  209. void
  210. CmpGuidOle(IUnknown* obj, REFIID req, void far*far* pif)
  211. {
  212.   if ( ((long*)&req)[1] == 0x00000000L &&
  213.        ((long*)&req)[2] == 0x000000C0L &&
  214.        ((long*)&req)[3] == 0x46000000L ) {
  215.     *pif = obj;
  216.     obj->AddRef();
  217.   }
  218. }
  219.  
  220. #if defined(BI_NAMESPACE)
  221. } // namespace OCF
  222. #endif
  223.  
  224. //----------------------------------------------------------------------------
  225. // TUnknown - standard implementation of IUnknown
  226. //
  227.  
  228. //
  229. // Handy container to help watch COM object lifetime when debugging
  230. //
  231. #if (__DEBUG >= 2)
  232. # include <classlib/bags.h>
  233.   typedef TBagAsVector<TUnknown*> TUnknownBag;
  234.   TUnknownBag* UnknownBag;
  235. #endif
  236.  
  237. //
  238. //
  239. //
  240. TUnknown::TUnknown()
  241.          :Outer(&I)
  242. {
  243. #if (__DEBUG >= 2)
  244.   if (!UnknownBag)
  245.     UnknownBag = new TUnknownBag(100);
  246.   UnknownBag->Add(this);
  247. #endif
  248. }
  249.  
  250. //
  251. //
  252. //
  253. IUnknown&
  254. TUnknown::Aggregate(TUnknown& inner)
  255. {
  256.   if (I.Inner)
  257.     return I.Inner->Aggregate(inner);
  258.   ((IUnknown&)inner).AddRef();
  259.   I.Inner = &inner;
  260.   return *Outer;
  261. }
  262.  
  263. //
  264. //
  265. //
  266. TUnknown::~TUnknown()
  267. {
  268. #if (__DEBUG >= 2)
  269.   UnknownBag->Detach(this);
  270. #endif
  271.   TRACEX(OcRefCount, 1,
  272.          "~TUnknown() @" << (void*)this << ", RefCnt:" << I.RefCnt);
  273.   WARNX(OcRefCount, I.RefCnt != 0, 0,
  274.         "~TUnknown() @ " << (void*)this << ", RefCnt:" << I.RefCnt);
  275.  
  276.   // deleted by TUnknownI member
  277. }
  278.  
  279. //
  280. // QueryObject used when TUnknown is in constructor/destructor
  281. //
  282. HRESULT
  283. TUnknown::QueryObject(const GUID far& /*iid*/, void far* far* /*pif*/)
  284. {
  285.   return ResultFromScode(E_NOINTERFACE);
  286. }
  287.  
  288. //
  289. //
  290. //
  291. HRESULT _IFUNC
  292. TUnknown::TUnknownI::QueryInterface(const GUID far& iid, void far* far* pif)
  293. {
  294.   *pif = 0;
  295.   if (iid.Data1 == 0) { // IID_IUnknown.Data1
  296.     CmpGuidOle(this, iid, pif);
  297.     if (*pif)
  298.       return NOERROR;
  299.   }
  300.   if (Host().QueryObject(iid, pif) == NOERROR)
  301.     return NOERROR;
  302.   if (Inner)
  303.     return Inner->ThisUnknown().QueryInterface(iid, pif);
  304.   else
  305.     return ResultFromScode(E_NOINTERFACE);
  306. }
  307.  
  308. //
  309. //
  310. //
  311. unsigned long _IFUNC
  312. TUnknown::TUnknownI::AddRef()
  313. {
  314.   TRACEX(OcRefCount, 1,
  315.          "AddRef on " << _TYPENAME(&Host()) << ' ' << (void*)&Host() << " to " << (RefCnt+1));
  316.   return ++RefCnt;
  317. }
  318.  
  319. //
  320. //
  321. //
  322. unsigned long _IFUNC
  323. TUnknown::TUnknownI::Release()
  324. {
  325.   TRACEX(OcRefCount, 1,
  326.          "Release on " << _TYPENAME(&Host()) << ' ' << (void*)&Host() << " to " << (RefCnt-1));
  327.   if (--RefCnt != 0)
  328.     return RefCnt;
  329.   if (Inner) {
  330.     Inner->ThisUnknown().Release();
  331.     Inner = 0;
  332.   }
  333.   delete &Host();
  334.   return 0;
  335. }
  336.  
  337. //
  338. //
  339. //
  340. unsigned long
  341. TUnknown::GetRefCount()
  342. {
  343.   if (Outer == &I)
  344.     return I.RefCnt;
  345.   Outer->AddRef();
  346.   return Outer->Release();
  347. }
  348.  
  349. //
  350. //
  351. //
  352. TUnknown::TUnknownI::~TUnknownI()
  353. {
  354.   // In case destructor called before RefCnt goes to 0
  355.   //
  356.   if (RefCnt)
  357.     ::CoDisconnectObject(this,0);// OLE will try to remove external references
  358. }
  359.  
  360. //----------------------------------------------------------------------------
  361. // Pixel <-> HiMetric conversion routines
  362. //
  363. static int logPixX = 0;
  364. static int logPixY = 0;
  365.  
  366. //
  367. //
  368. static void
  369. GetScreenMetrics(int& logPixX, int& logPixY)
  370. {
  371.   HDC hDCScreen = GetDC(0);
  372.   logPixX = GetDeviceCaps(hDCScreen, LOGPIXELSX);
  373.   logPixY = GetDeviceCaps(hDCScreen, LOGPIXELSY);
  374.   ReleaseDC(0, hDCScreen);
  375. }
  376.  
  377. //
  378. //
  379. //
  380. void
  381. OcHiMetricToPixel(const SIZEL& sizeHM, SIZEL& sizePix)
  382. {
  383.   if (!logPixX || !logPixY)
  384.     GetScreenMetrics(logPixX, logPixY);
  385.  
  386.   sizePix.cx = MAP_LOGHIM_TO_PIX(sizeHM.cx, logPixX);
  387.   sizePix.cy = MAP_LOGHIM_TO_PIX(sizeHM.cy, logPixY);
  388. }
  389.  
  390. //
  391. //
  392. //
  393. void
  394. OcPixelToHiMetric(const SIZEL& sizePix, SIZEL& sizeHM)
  395. {
  396.   if (!logPixX || !logPixY)
  397.     GetScreenMetrics(logPixX, logPixY);
  398.  
  399.   sizeHM.cx = MAP_PIX_TO_LOGHIM(sizePix.cx, logPixX);
  400.   sizeHM.cy = MAP_PIX_TO_LOGHIM(sizePix.cy, logPixY);
  401. }
  402.  
  403. //----------------------------------------------------------------------------
  404. // TLocaleString wrapper method replacements using OLE2 NLS functions for Win16
  405. //
  406.  
  407. #if defined(BI_PLAT_WIN16)
  408.  
  409. //
  410. //
  411. //
  412. TLangId
  413. TLocaleString::GetSystemLangId()
  414. {
  415.   return ::GetSystemDefaultLangID();
  416. }
  417.  
  418. //
  419. //
  420. //
  421. TLangId
  422. TLocaleString::GetUserLangId()
  423. {
  424.   return ::GetUserDefaultLangID();
  425. }
  426.  
  427. //
  428. //
  429. //
  430. int
  431. TLocaleString::CompareLang(const char far* s1, const char far* s2, TLangId lang)
  432. {
  433.   return ::CompareStringA(lang, NORM_IGNORECASE | NORM_IGNORENONSPACE,
  434.                           s1,-1, s2,-1) - 2;
  435. }
  436.  
  437. #endif
  438.